package io;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 通过提高每次读写的数据量减少实际读写的次数，可以提高读写的效率
 * 一组字节的读写:块读写形式
 */
public class CopyDemo2 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("bg.jpg");
        FileOutputStream fos = new FileOutputStream("bg_cp2.jpg");
        /*
            InputStream超类中定义了块读取数据的方法:
            int read(byte[] data)
            一次性读取给定的字节数组data总长度的字节量，并存入到该数组中。返回值
            表达实际读取到了多少个字节。如果返回值为-1则表达流读取到了末尾。

            bg.jpg文件数据(7个字节):
            11001100 00110011 10101010 01010101 11110000 00110011 11000011

            byte[] data = new byte[3];//长度为3字节的数组
            data:{00000000,00000000,00000000} //data数组每个元素2进制样子
            int len;//记录每次读取的字节数


            当第一次调用:len=fis.read(data);//由于data数组长度为3，因此一次性要读取3字节
            bg.jpg文件数据:
            11001100 00110011 10101010 01010101 11110000 00110011 11000011
            ^^^^^^^^ ^^^^^^^^ ^^^^^^^^
            |----本次读取到的3个字节----|

            data:{11001100,00110011,10101010}
                  |-----本次读取的3个字节-----|
            len:3 len的值为整数3，表示本次实际读取到了3个字节




            当第二次调用:len=fis.read(data);//由于data数组长度为3，因此一次性要读取3字节
            bg.jpg文件数据:
            11001100 00110011 10101010 01010101 11110000 00110011 11000011
                                       ^^^^^^^^ ^^^^^^^^ ^^^^^^^^
                                       |-----本次读取的3个字节-----|

            data:{01010101 11110000 00110011}
                  |-----本次读取的3个字节-----|
            len:3 len的值为整数3，表示本次实际读取到了3个字节




            当第三次调用:len=fis.read(data);//由于data数组长度为3，因此一次性要读取3字节
            bg.jpg文件数据:
            11001100 00110011 10101010 01010101 11110000 00110011 11000011 文件末尾
                                                                  ^^^^^^^^ ^^^^^^^^ ^^^^^^^^
                                                                  仅读取1字节

            data:{11000011 11110000 00110011}
                  |-读取的-||-----旧数据------|
            len:1 len的值为整数1，表示读取了1个字节



            当第四次调用:len=fis.read(data);//由于data数组长度为3，因此一次性要读取3字节
            bg.jpg文件数据:
            11001100 00110011 10101010 01010101 11110000 00110011 11000011 文件末尾
                                                                           ^^^^^^^^ ^^^^^^^^ ^^^^^^^^


            data:{11000011 11110000 00110011}
                  |---------旧数据----------|
            len:-1 len的值为整数-1，表示流读取到了末尾




            OutputStream超类上也提供了块写字节的方法
            void write(byte[] data)
            一次性将给定的字节数组中所有字节写出

            void write(byte[] data,int offset,int len)
            一次性将给定的字节数组data从下标offset处开始的连续len个字节写出
         */
        /*
            00000000   8位2进制称为1字节  1byte
            1024byte   1kb
            1024kb     1mb
            1024mb     1gb
            1024gb     1tb
            1024tb     1pb
         */
        byte[] data = new byte[1024*10];//10kb
        int len;//记录每次实际读取的数据量
        long start = System.currentTimeMillis();
        while((len = fis.read(data)) != -1){//每次读取10kb并判断是否读取到了末尾
            //将字节数组从下标0开始的连续len个字节写出(做到本次读取多少写多少)
            fos.write(data,0,len);
        }
        long end = System.currentTimeMillis();
        System.out.println("复制完毕!耗时:"+(end-start)+"ms");
        fis.close();
        fos.close();
    }
}
